package com.yc.sole.system.biz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.yc.sole.framework.mybatis.page.Paging;
import com.yc.sole.framework.mybatis.util.PageUtil;
import com.yc.sole.system.dto.RoleDto;
import com.yc.sole.system.dto.RoleMenuDto;
import com.yc.sole.system.request.RoleMenuReq;
import com.yc.sole.system.request.RoleQueryReq;
import com.yc.sole.system.request.RoleReq;
import com.yc.sole.system.repository.RoleMenuRepository;
import com.yc.sole.system.repository.RoleRepository;
import com.yc.sole.system.repository.UserRoleRepository;
import com.yc.sole.system.response.RoleResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 服务接口实现
 *
 * @author yizuomin
 * @date 2023-03-26
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleBiz {

    private final RoleRepository roleRepository;
    private final RoleMenuRepository roleMenuRepository;
    private final UserRoleRepository userRoleRepository;

    /**
     * 新增
     *
     * @param roleReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveRole(RoleReq roleReq) {
        RoleDto dto = new RoleDto();
        BeanUtil.copyProperties(roleReq, dto);
        roleRepository.saveRole(dto);
    }

    /**
     * 修改
     *
     * @param roleReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRoleById(RoleReq roleReq) {
        RoleDto dto = new RoleDto();
        BeanUtil.copyProperties(roleReq, dto);
        roleRepository.updateRoleById(dto);
    }

    /**
     * 分配权限
     *
     * @param roleMenuReq
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRolePermission(RoleMenuReq roleMenuReq) {
        //删除角色菜单关联
        roleMenuRepository.deleteRoleMenuByRoleId(Lists.newArrayList(roleMenuReq.getId()));
        //新增角色菜单关联
        if (CollUtil.isNotEmpty(roleMenuReq.getMenuIds())) {
            roleMenuRepository.saveBatchRoleMenu(roleMenuReq.getMenuIds().stream().map(menuId -> {
                RoleMenuDto roleMenuDto = new RoleMenuDto();
                roleMenuDto.setMenuId(menuId);
                roleMenuDto.setRoleId(roleMenuReq.getId());
                return roleMenuDto;
            }).toList());
        }
    }

    /**
     * 删除
     *
     * @param ids
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(Collection<Long> ids) {
        // 删除角色
        roleRepository.deleteRole(ids);
        //删除角色菜单关联
        roleMenuRepository.deleteRoleMenuByRoleId(ids);
        //删除用户角色关联
        userRoleRepository.deleteUserRoleByRoleId(ids);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param roleQueryReq
     * @return
     */
    public Paging<RoleResp> selectRolePage(Paging<RoleQueryReq> page, RoleQueryReq roleQueryReq) {
        Paging<RoleDto> paging = roleRepository.selectRolePage(page, roleQueryReq);
        return PageUtil.pageCopy(paging, RoleResp.class);
    }

    /**
     * 查询所有角色
     *
     * @return
     */
    public List<RoleResp> selectRoleList() {
        return BeanUtil.copyToList(roleRepository.selectAll(), RoleResp.class);
    }

    /**
     * 根据id查询角色
     *
     * @param id
     * @return
     */
    public RoleResp selectRoleById(Long id) {
        RoleDto roleDto = roleRepository.selectRoleById(id);
        if (Objects.isNull(roleDto)) {
            return null;
        }
        RoleResp roleResp = BeanUtil.copyProperties(roleDto, RoleResp.class);
        return roleResp;
    }

    /**
     * 查询角色拥有菜单
     *
     * @param id
     * @return
     */
    public Collection<Long> selectMenuIds(Long id) {
        List<RoleMenuDto> roleMenuDtos = roleMenuRepository.selectByRoleId(id);
        return roleMenuDtos.stream().map(RoleMenuDto::getMenuId).collect(Collectors.toSet());
    }
}
